home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap20 / Multi2 / Multi2.c next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  10.8 KB  |  376 lines

  1. /*---------------------------------------
  2.    MULTI2.C -- Multitasking Demo
  3.                (c) Charles Petzold, 1998
  4.   ---------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <math.h>
  8. #include <process.h>
  9.  
  10. typedef struct
  11. {
  12.      HWND hwnd ;
  13.      int  cxClient ;
  14.      int  cyClient ;
  15.      int  cyChar ;
  16.      BOOL bKill ;
  17. }
  18. PARAMS, *PPARAMS ;
  19.  
  20. LRESULT APIENTRY WndProc (HWND, UINT, WPARAM, LPARAM) ;
  21.  
  22. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  23.                     PSTR szCmdLine, int iCmdShow)
  24. {
  25.      static TCHAR szAppName[] = TEXT ("Multi2") ;
  26.      HWND         hwnd ;
  27.      MSG          msg ;
  28.      WNDCLASS     wndclass ;
  29.      
  30.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  31.      wndclass.lpfnWndProc   = WndProc ;
  32.      wndclass.cbClsExtra    = 0 ;
  33.      wndclass.cbWndExtra    = 0 ;
  34.      wndclass.hInstance     = hInstance ;
  35.      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  36.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  37.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  38.      wndclass.lpszMenuName  = NULL ;
  39.      wndclass.lpszClassName = szAppName ;
  40.      
  41.      if (!RegisterClass (&wndclass))
  42.      {
  43.           MessageBox (NULL, TEXT ("This program requires Windows NT!"),
  44.                       szAppName, MB_ICONERROR) ;
  45.           return 0 ;
  46.      }
  47.      
  48.      hwnd = CreateWindow (szAppName, TEXT ("Multitasking Demo"),
  49.                           WS_OVERLAPPEDWINDOW,
  50.                           CW_USEDEFAULT, CW_USEDEFAULT,
  51.                           CW_USEDEFAULT, CW_USEDEFAULT,
  52.                           NULL, NULL, hInstance, NULL) ;
  53.      
  54.      ShowWindow (hwnd, iCmdShow) ;
  55.      UpdateWindow (hwnd) ;
  56.      
  57.      while (GetMessage (&msg, NULL, 0, 0))
  58.      {
  59.           TranslateMessage (&msg) ;
  60.           DispatchMessage (&msg) ;
  61.      }
  62.      return msg.wParam ;
  63. }
  64.  
  65. int CheckBottom (HWND hwnd, int cyClient, int cyChar, int iLine)
  66. {
  67.      if (iLine * cyChar + cyChar > cyClient)
  68.      {
  69.           InvalidateRect (hwnd, NULL, TRUE) ;
  70.           UpdateWindow (hwnd) ;
  71.           iLine = 0 ;
  72.      }
  73.      return iLine ;
  74. }
  75.  
  76. // ------------------------------------------------
  77. // Window 1: Display increasing sequence of numbers
  78. // ------------------------------------------------
  79.  
  80. void Thread1 (PVOID pvoid)
  81. {
  82.      HDC     hdc ;
  83.      int     iNum = 0, iLine = 0 ;
  84.      PPARAMS pparams ;
  85.      TCHAR   szBuffer[16] ;
  86.      
  87.      pparams = (PPARAMS) pvoid ;
  88.      
  89.      while (!pparams->bKill)
  90.      {
  91.           if (iNum < 0)
  92.                iNum = 0 ;
  93.           
  94.           iLine = CheckBottom (pparams->hwnd,   pparams->cyClient,
  95.                                pparams->cyChar, iLine) ;
  96.  
  97.           hdc = GetDC (pparams->hwnd) ;
  98.           
  99.           TextOut (hdc, 0, iLine * pparams->cyChar, szBuffer, 
  100.                    wsprintf (szBuffer, TEXT ("%d"), iNum++)) ;               
  101.           
  102.           ReleaseDC (pparams->hwnd, hdc) ;
  103.           iLine++ ;
  104.      }
  105.      _endthread () ;
  106. }
  107.  
  108. LRESULT APIENTRY WndProc1 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  109. {
  110.      static PARAMS params ;
  111.      
  112.      switch (message)
  113.      {
  114.      case WM_CREATE:
  115.           params.hwnd = hwnd ;
  116.           params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
  117.           _beginthread (Thread1, 0, ¶ms) ;
  118.           return 0 ;
  119.           
  120.      case WM_SIZE:
  121.           params.cyClient = HIWORD (lParam) ;
  122.           return 0 ;
  123.           
  124.      case WM_DESTROY:
  125.           params.bKill = TRUE ;
  126.           return 0 ;
  127.      }
  128.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  129. }
  130.  
  131. // ------------------------------------------------------
  132. // Window 2: Display increasing sequence of prime numbers
  133. // ------------------------------------------------------
  134.  
  135. void Thread2 (PVOID pvoid)
  136. {
  137.      HDC     hdc ;
  138.      int     iNum = 1, iLine = 0, i, iSqrt ;
  139.      PPARAMS pparams ;
  140.      TCHAR   szBuffer[16] ;
  141.      
  142.      pparams = (PPARAMS) pvoid ;
  143.      
  144.      while (!pparams->bKill)
  145.      {
  146.           do
  147.           {
  148.                if (++iNum < 0)
  149.                     iNum = 0 ;
  150.                
  151.                iSqrt = (int) sqrt (iNum) ;
  152.                
  153.                for (i = 2 ; i <= iSqrt ; i++)
  154.                     if (iNum % i == 0)
  155.                          break ;
  156.           }
  157.           while (i <= iSqrt) ;
  158.           
  159.           iLine = CheckBottom (pparams->hwnd,   pparams->cyClient,
  160.                                pparams->cyChar, iLine) ;
  161.           
  162.           hdc = GetDC (pparams->hwnd) ;
  163.           
  164.           TextOut (hdc, 0, iLine * pparams->cyChar, szBuffer, 
  165.                    wsprintf (szBuffer, TEXT ("%d"), iNum)) ;
  166.           
  167.           ReleaseDC (pparams->hwnd, hdc) ;
  168.           iLine++ ;
  169.      }
  170.      _endthread () ;
  171. }
  172.  
  173. LRESULT APIENTRY WndProc2 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  174. {
  175.      static PARAMS params ;
  176.      
  177.      switch (message)
  178.      {
  179.      case WM_CREATE:
  180.           params.hwnd = hwnd ;
  181.           params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
  182.           _beginthread (Thread2, 0, ¶ms) ;
  183.           return 0 ;
  184.           
  185.      case WM_SIZE:
  186.           params.cyClient = HIWORD (lParam) ;
  187.           return 0 ;
  188.           
  189.      case WM_DESTROY:
  190.           params.bKill = TRUE ;
  191.           return 0 ;
  192.      }
  193.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  194. }
  195.  
  196. // Window 3: Display increasing sequence of Fibonacci numbers
  197. // ----------------------------------------------------------
  198.  
  199. void Thread3 (PVOID pvoid)
  200. {
  201.      HDC     hdc ;
  202.      int     iNum = 0, iNext = 1, iLine = 0, iTemp ;
  203.      PPARAMS pparams ;
  204.      TCHAR   szBuffer[16] ;
  205.      
  206.      pparams = (PPARAMS) pvoid ;
  207.      
  208.      while (!pparams->bKill)
  209.      {
  210.           if (iNum < 0)
  211.           {
  212.                iNum  = 0 ;
  213.                iNext = 1 ;
  214.           }
  215.           iLine = CheckBottom (pparams->hwnd,   pparams->cyClient,
  216.                                pparams->cyChar, iLine) ;
  217.  
  218.           hdc = GetDC (pparams->hwnd) ;
  219.           
  220.           TextOut (hdc, 0, iLine * pparams->cyChar, szBuffer, 
  221.                    wsprintf (szBuffer, TEXT ("%d"), iNum)) ;
  222.           
  223.           ReleaseDC (pparams->hwnd, hdc) ;
  224.           iTemp  = iNum ;
  225.           iNum   = iNext ;
  226.           iNext += iTemp ;
  227.           iLine++ ;
  228.      }
  229.      _endthread () ;
  230. }
  231.  
  232. LRESULT APIENTRY WndProc3 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  233. {
  234.      static PARAMS params ;
  235.      
  236.      switch (message)
  237.      {
  238.      case WM_CREATE:
  239.           params.hwnd = hwnd ;
  240.           params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
  241.           _beginthread (Thread3, 0, ¶ms) ;
  242.           return 0 ;
  243.           
  244.      case WM_SIZE:
  245.           params.cyClient = HIWORD (lParam) ;
  246.           return 0 ;
  247.           
  248.      case WM_DESTROY:
  249.           params.bKill = TRUE ;
  250.           return 0 ;
  251.      }
  252.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  253. }
  254.  
  255. // -----------------------------------------
  256. // Window 4: Display circles of random radii
  257. // -----------------------------------------
  258.  
  259. void Thread4 (PVOID pvoid)
  260. {
  261.      HDC     hdc ;
  262.      int     iDiameter ;
  263.      PPARAMS pparams ;
  264.      
  265.      pparams = (PPARAMS) pvoid ;
  266.      
  267.      while (!pparams->bKill)
  268.      {
  269.           InvalidateRect (pparams->hwnd, NULL, TRUE) ;
  270.           UpdateWindow (pparams->hwnd) ;
  271.           
  272.           iDiameter = rand() % (max (1,
  273.                                 min (pparams->cxClient, pparams->cyClient))) ;
  274.           
  275.           hdc = GetDC (pparams->hwnd) ;
  276.           
  277.           Ellipse (hdc, (pparams->cxClient - iDiameter) / 2,
  278.                         (pparams->cyClient - iDiameter) / 2,
  279.                         (pparams->cxClient + iDiameter) / 2,
  280.                         (pparams->cyClient + iDiameter) / 2) ;
  281.           
  282.           ReleaseDC (pparams->hwnd, hdc) ;
  283.      }
  284.      _endthread () ;
  285. }
  286.  
  287. LRESULT APIENTRY WndProc4 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  288. {
  289.      static PARAMS params ;
  290.      
  291.      switch (message)
  292.      {
  293.      case WM_CREATE:
  294.           params.hwnd = hwnd ;
  295.           params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
  296.           _beginthread (Thread4, 0, ¶ms) ;
  297.           return 0 ;
  298.           
  299.      case WM_SIZE:
  300.           params.cxClient = LOWORD (lParam) ;
  301.           params.cyClient = HIWORD (lParam) ;
  302.           return 0 ;
  303.           
  304.      case WM_DESTROY:
  305.           params.bKill = TRUE ;
  306.           return 0 ;
  307.      }
  308.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  309. }
  310.  
  311. // -----------------------------------
  312. // Main window to create child windows
  313. // -----------------------------------
  314.  
  315. LRESULT APIENTRY WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  316. {
  317.      static HWND    hwndChild[4] ;
  318.      static TCHAR * szChildClass[] = { TEXT ("Child1"), TEXT ("Child2"),
  319.                                        TEXT ("Child3"), TEXT ("Child4") } ;
  320.      static WNDPROC ChildProc[] = { WndProc1, WndProc2, WndProc3, WndProc4 } ;
  321.      HINSTANCE      hInstance ;
  322.      int            i, cxClient, cyClient ;
  323.      WNDCLASS       wndclass ;
  324.      
  325.      switch (message)
  326.      {
  327.      case WM_CREATE:
  328.           hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;
  329.           
  330.           wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  331.           wndclass.cbClsExtra    = 0 ;
  332.           wndclass.cbWndExtra    = 0 ;
  333.           wndclass.hInstance     = hInstance ;
  334.           wndclass.hIcon         = NULL ;
  335.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  336.           wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  337.           wndclass.lpszMenuName  = NULL ;
  338.           
  339.           for (i = 0 ; i < 4 ; i++)
  340.           {
  341.                wndclass.lpfnWndProc   = ChildProc[i] ;
  342.                wndclass.lpszClassName = szChildClass[i] ;
  343.                
  344.                RegisterClass (&wndclass) ;
  345.                
  346.                hwndChild[i] = CreateWindow (szChildClass[i], NULL,
  347.                                    WS_CHILDWINDOW | WS_BORDER | WS_VISIBLE,
  348.                                    0, 0, 0, 0, 
  349.                                    hwnd, (HMENU) i, hInstance, NULL) ;
  350.           }
  351.           
  352.           return 0 ;
  353.           
  354.      case WM_SIZE:
  355.           cxClient = LOWORD (lParam) ;
  356.           cyClient = HIWORD (lParam) ;
  357.           
  358.           for (i = 0 ; i < 4 ; i++)
  359.                MoveWindow (hwndChild[i], (i % 2) * cxClient / 2,
  360.                                          (i > 1) * cyClient / 2,
  361.                            cxClient / 2, cyClient / 2, TRUE) ;
  362.           return 0 ;
  363.           
  364.      case WM_CHAR:
  365.           if (wParam == '\x1B')
  366.                DestroyWindow (hwnd) ;
  367.           
  368.           return 0 ;
  369.           
  370.      case WM_DESTROY:
  371.           PostQuitMessage (0) ;
  372.           return 0 ;
  373.      }
  374.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  375. }
  376.